﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows;

namespace Sparkle.UI
{

    #region BindingEventArgs

    public class BindingEventArgs
    {
        public Metadata Metadata { get; set; }

        public Control Control { get; set; }

        public object Entity { get; set; }

        public bool DataBinded = false;
    }

    public class CreateControlEventArgs
    {
        public Metadata Metadata { get; set; }

        public Control Control { get; set; }

        public bool ControlCreated = false;
    }
    #endregion

    public delegate void BindingHandler(object sender, BindingEventArgs e);

    public delegate void CreateControlHandler(object sender, CreateControlEventArgs e);

    #region BaseControlFactory

    public abstract class BaseControlFactory : IControlFactory
    {
        #region Create control (To create control dynamicaly as per metadata)

        public abstract Control CreateControl(Metadata metadata);

        public abstract event CreateControlHandler OnControlCreate;
        public abstract event CreateControlHandler OnUnknownControl;

        public abstract TextBlock CreateLabel(Metadata metadata, double width);

        #endregion

        #region Data binding (to bind data with entity as per metadata)


        public abstract event BindingHandler OnBinding;
        public abstract event BindingHandler OnUnknownBinding;

        public abstract void SetBinding(Control control, Metadata metadata, object entity);

        #endregion

        #region Create Column
#if SILVERLIGHT
        public abstract DataGridColumn CreateColumn(Metadata metadata);
        public abstract void SetBinding(DataGridColumn column, Metadata metadata);
#else
        public abstract ColumnDefinition CreateColumn(Metadata metadata);
        public abstract void SetBinding(ColumnDefinition column, Metadata metadata);
#endif

        #endregion

        #region Error Control
        public abstract TextBlock CreateErrorControl(string errorMessage);
        #endregion
    }

    #endregion

    #region ControlFactory

    /// <summary>
    /// ControlFactory create the controls as per entity's metadata
    /// </summary>
    public class ControlFactory : BaseControlFactory
    {
        public override event BindingHandler OnBinding;
        public override event BindingHandler OnUnknownBinding;

        public override event CreateControlHandler OnControlCreate;
        public override event CreateControlHandler OnUnknownControl;

        public ControlFactory()
        {
            OnControlCreate += new CreateControlHandler(ControlFactory_OnControlCreate);
            OnUnknownControl += new CreateControlHandler(ControlFactory_OnUnknownControl);
            OnBinding += new BindingHandler(ControlFactory_OnBinding);
            OnUnknownBinding += new BindingHandler(ControlFactory_OnUnknownBinding);
        }

        #region global event code

        void ControlFactory_OnUnknownControl(object sender, CreateControlEventArgs e)
        {
            ;
        }

        void ControlFactory_OnControlCreate(object sender, CreateControlEventArgs e)
        {
            ;
        }

        void ControlFactory_OnUnknownBinding(object sender, BindingEventArgs e)
        {
            ;
        }

        void ControlFactory_OnBinding(object sender, BindingEventArgs e)
        {
            ;
        }

        #endregion


        #region CreateControl

        /// <summary>
        /// Creates the control as per metadata.
        /// </summary>
        /// <param name="metadata">The metadata.</param>
        /// <returns></returns>
        public override Control CreateControl(Metadata metadata)
        {
            Control control = null;

            IRegisterdControl registeredControl = null;

            if (metadata == null)
                return control;

            CreateControlEventArgs CreateControlArgs = new CreateControlEventArgs() { Metadata = metadata, Control = control };

            OnControlCreate(this, CreateControlArgs);

            if (CreateControlArgs.ControlCreated)
            {
                return CreateControlArgs.Control;
            }

            Type registeredType = UIDefaults.GetRegisterdControlType(metadata.MetaType);

            if (registeredType != null)
            {
                registeredControl = UIDefaults.RegisterdControls[registeredType];

                if (registeredControl != null)
                {
                    control = registeredControl.CteateControl(metadata);
                }
            }

            if (control == null)
            {
                OnUnknownControl(this, CreateControlArgs);
                control = CreateControlArgs.Control;
            }

            if (control != null)
            {
                control.IsEnabled = metadata.Enable;

                if (registeredControl.DefaultWidth > 0)
                {
                    control.Width = registeredControl.DefaultWidth;
                }

                if (registeredControl.DefaultHeight > 0)
                {
                    control.Height = registeredControl.DefaultHeight;
                }
            }

            return control;
        }

        #endregion

        #region Data Binding

        /// <summary>
        /// Sets the data binding with entity.
        /// </summary>
        /// <param name="control">The control.</param>
        /// <param name="metadata">The metadata.</param>
        /// <param name="entity">The entity.</param>
        public override void SetBinding(Control control, Metadata metadata, object entity)
        {
            BindingEventArgs bindingArgs = new BindingEventArgs()
            {
                Entity = entity,
                Metadata = metadata,
                Control = control
            };

            OnBinding(this, bindingArgs);

            if (bindingArgs.DataBinded)
                return;

            Type registeredType = UIDefaults.GetRegisterdControlType(metadata.MetaType);

            if (registeredType != null)
            {
                IRegisterdControl registeredControl = UIDefaults.RegisterdControls[registeredType];

                try
                {
                    registeredControl.SetBinding(control,metadata, entity); 
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine("Exception :" + ex.Message);
                }
            }
        }

        #endregion

        #region Create Label for control

        /// <summary>
        /// Creates the label as per metadata.
        /// </summary>
        /// <param name="metadata">The metadata.</param>
        /// <param name="width">The width.</param>
        /// <returns></returns>
        public override TextBlock CreateLabel(Metadata metadata, double width)
        {
            TextBlock tmpTxtblock = UIDefaults.CreateLabelControl();

            tmpTxtblock.Text = metadata.Title;
            tmpTxtblock.Width = width;

            return tmpTxtblock;
        }

        #endregion

        #region Create Error Control

        public override TextBlock CreateErrorControl(string errorMessage)
        {
            TextBlock tmpErrblock = UIDefaults.CreateErrorControl();

            tmpErrblock.Text = errorMessage;

            return tmpErrblock;

        }

        #endregion

        #region Grid Defaults code

        #region Create data Column

#if SILVERLIGHT
        public override DataGridColumn CreateColumn(Metadata metadata)
#else
        public override ColumnDefinition CreateColumn(Metadata metadata)
#endif

        {
#if SILVERLIGHT
            DataGridColumn column = null;
#else
            ColumnDefinition column = null;
#endif

            RegisterdColumn regColumn = null;

            if (UIDefaults.IsRegisterdColumn(metadata.MetaType))
            {
                regColumn = UIDefaults.RegisterdColumns[metadata.MetaType];
#if SILVERLIGHT
                column = Activator.CreateInstance(regColumn.ColumnType) as DataGridColumn;
#else
                column = Activator.CreateInstance(regColumn.ColumnType) as ColumnDefinition;
#endif

            }
            if (column == null)
            {
#if SILVERLIGHT
                column = new DataGridTextColumn();
#else
                column = new ColumnDefinition();
#endif

            }
            if (column != null)
            {
#if SILVERLIGHT
                column.IsReadOnly = column.IsReadOnly ? true : metadata.ReadOnly;
                column.Header = metadata.Title;

                if (regColumn != null && regColumn.DefaultWidth > 0)
                { column.Width = new DataGridLength(regColumn.DefaultWidth); }
#else
                column.IsEnabled = column.IsEnabled ? true : metadata.ReadOnly;
                column.Name = metadata.Title;

                if (regColumn != null && regColumn.DefaultWidth > 0)
                { column.Width = new GridLength(regColumn.DefaultWidth); }
#endif

            }
            return column;
        }

        #endregion

        #region Set data Binding for column
#if SILVERLIGHT
        public override void SetBinding(DataGridColumn column, Metadata metadata)
#else
        public override void SetBinding(ColumnDefinition column, Metadata metadata)
#endif

        {
#if SILVERLIGHT
            if (column is DataGridColumn)
            {
                //(column as ColumnDefinition).Binding = new Binding(metadata.Name);
            }
#endif
            RegisterdColumn regColumn = null;

            if (UIDefaults.IsRegisterdColumn(metadata.MetaType))
            {
                regColumn = UIDefaults.RegisterdColumns[metadata.MetaType];
                if (regColumn != null && regColumn.OnDataBinding != null)
                {
                    regColumn.OnDataBinding(column);
                }
            }
        }
        #endregion

        #endregion
    }

    #endregion
}
